﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;
using Roslyn.Services;
using Microsoft.Build.Execution;

namespace RoslynCompiler
{
    class Program
    {
        static void Main(string[] args)
        {
            string solutionPath = new DirectoryInfo(args[0]).FullName;
            string binaryDirectory = new DirectoryInfo(args[1]).FullName;

            string modifiedDirectory = Path.Combine(binaryDirectory, "Modified Code");

            string solutionDirectoryPath = Path.GetDirectoryName(solutionPath);
            new DirectoryInfo(solutionDirectoryPath).CopyContent(new DirectoryInfo(modifiedDirectory));

            var solution = Solution.Load(solutionPath);

            List<IProject> notSortedProjects = solution.Projects.ToList();
            List<IProject> projects = new List<IProject>();
            do
            {
                foreach (IProject project in notSortedProjects.ToList())
                {
                    if (project.ProjectReferences.All(prId => projects.Any(p => p.Id == prId)))
                    {
                        projects.Add(project);
                        notSortedProjects.Remove(project);
                    }
                }
            } while (notSortedProjects.Count != 0);

            var documentRewriter = new DocumentRewriter();

            for (documentRewriter.RewriterIndex = 0; documentRewriter.RewriterIndex < documentRewriter.RewriterIndexMax; documentRewriter.RewriterIndex++)
                foreach (var project in projects.Select(p => solution.Projects.First(p2 => p2.Id == p.Id)))
                    foreach (var document in project.Documents)
                    {
                        var documentTree = document.GetSyntaxTree();
                        documentRewriter.SemanticModel = project.GetCompilation().GetSemanticModel(documentTree);
                        var documentNewTree = documentRewriter.Visit((SyntaxNode)documentTree.Root);
                        if (documentNewTree == documentTree.Root)
                            continue;
                        var newTreeText = new StringText(documentNewTree.Format().ToString());
                        solution = solution.UpdateDocument(document.Id, newTreeText);
                        using (var sw = new StreamWriter(Path.Combine(modifiedDirectory, document.Id.FileName.Substring(solutionDirectoryPath.Length + 1))))
                        {
                            sw.Write(documentNewTree.Format().ToString());
                        }
                    }


            //foreach (var project in projects.Select(p => solution.Projects.First(p2 => p2.Id == p.Id)))
            //    using (var stream = new FileStream(string.Format("{0}.{1}", Path.Combine(binaryDirectory, project.AssemblyName), project.CompilationOptions.AssemblyKind == AssemblyKind.DynamicallyLinkedLibrary ? "dll" : "exe"), FileMode.Create))
            //    {
            //        var emitResult = solution.Projects.First(p => p.Id == project.Id).GetCompilation().Emit(stream);
            //        if (!emitResult.Success)
            //            throw new InvalidOperationException();
            //    }

            string mainProjectPath = args.Length > 2 ? args[2] : projects.Last().Id.Name;
            BuildRequestData BuidlRequest = new BuildRequestData(Path.Combine(modifiedDirectory, mainProjectPath.Substring(solutionDirectoryPath.Length + 1)), new Dictionary<string, string>() { { "Configuration", "Debug" }, { "Platform", "Any CPU" }, { "OutputPath", binaryDirectory } }, null, new string[] { "Build" }, null);
            BuildResult buildResult = BuildManager.DefaultBuildManager.Build(new BuildParameters(), BuidlRequest);
        }
    }
}
